import { message } from 'antd'
import { has } from 'lodash'
import { v4 as uuidv4 } from 'uuid'

import { Create, Enums, Users, Violations } from './api'
import { Violation } from './api/interface'
import store from './store'
import { get, getJson, set, setJson } from './utils/storage'

const getEnums = async () => {
  const enumData = await Promise.all([
    Enums({ type: 'ViolatorOrWitnessEnums' }),
    Enums({ type: 'NationalityEnums' }),
  ])

  setJson('ViolatorOrWitness', enumData[0].data)
  setJson('Nationality', enumData[1].data)
}

const getUser = async () => {
  const { data } = await Users()
  setJson('Users', data)
}

const getViolations = async () => {
  const { data } = await Violations()
  setJson(
    'Violations',
    data.map((a) => ({ id: a.id, refNumber: a.refNumber }))
  )
}

const upload = async (formData: FormData) => {
  try {
    store.dispatch({
      type: 'add-networks',
    })
    const token = store.getState().token ? store.getState().token : ''
    const response = await fetch(
      `${import.meta.env.VITE_BASE_API}/wajib/admin/investigation/upload`,
      {
        method: 'POST',
        body: formData,
        headers: {
          'Content-Type': 'multipart/form-data; boundary=----',
          did: token,
        },
      }
    )
    store.dispatch({
      type: 'sub-networks',
    })
    if (!response.ok) {
      throw new Error('上传失败')
    }
    const responseData = await response.json()
    if (responseData.code * 1 === 0) {
      return responseData.data
    } else if (responseData.code * 1 === 7000) {
      set('isCheck', false)
      set('isDeviceError', true)
      throw responseData
    } else {
      throw responseData
    }
  } catch (error) {
    store.dispatch({
      type: 'sub-networks',
    })
    throw error
  }
}

export const fileUpload = async (path: string) => {
  const newFormData = new FormData()
  const base64Regex = /^data:[\w\/\+-]+;base64,/
  if (base64Regex.test(path)) {
    // 解析Base64编码，获取文件类型和二进制数据
    const matches = path.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)
    const fileMimeType = matches[1]
    const fileData = matches[2]
    // 将Base64编码的文件转换为二进制数据
    const byteArray = Uint8Array.from(atob(fileData), (c) => c.charCodeAt(0))
    // 创建文件对象
    const file = new File([byteArray], 'filename.png', { type: fileMimeType })
    newFormData.append('file', file)
  } else {
    const readFile = window.electron.ipcRenderer.readFiles(path)
    if (!readFile) {
      return path
    }
    const { data, fileName } = readFile
    const fileData = new File([data], fileName)
    newFormData.append('file', fileData)
  }
  try {
    const url = await upload(newFormData)
    return url
  } catch (e) {
    return path
  }
}

const extractValues = async (obj: Partial<Violation>) => {
  for (const key in obj) {
    if (key === 'attachments' || key === 'attachment') {
      await Promise.all(
        obj[key].map(async (a, index) => {
          const url = await fileUpload(a)
          obj[key][index] = url
        })
      )
      continue
    }
    if (key === 'signature') {
      obj[key] = await fileUpload(obj[key])
      continue
    }
    if (key === 'signatures') {
      await Promise.all(
        obj[key].map(async (a, index) => {
          const url = await fileUpload(a.value)
          obj[key][index].value = url
        })
      )

      continue
    }
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      await extractValues(obj[key])
    }
  }
}

export const onCreate = async (violation: Partial<Violation>) => {
  if (!violation.checkCode) {
    violation.checkCode = uuidv4()
  }
  const networkStatus = get('networkStatus')
  const isDeviceError = get('isDeviceError')
  if (networkStatus && !isDeviceError) {
    try {
      await extractValues(violation)
      await Create(violation)
      createSuccess(violation)
    } catch (error) {
      console.log(error)
      if (has(error, 'data')) {
        console.log(error.data?.code)
        if (error.data?.code == 6003) {
          createSuccess(violation)
          return
        }
      }
      createFail(violation)
      throw error
    }
  } else {
    createFail(violation)
    throw new Error('No network')
  }
}

const createSuccess = (violation: Partial<Violation>) => {
  const violationList: Partial<Violation>[] = getJson('violationList') || []
  console.log(violation.checkCode, violationList)
  const newList = violationList.filter((a) => a.checkCode !== violation.checkCode)
  console.log(newList)
  setJson('violationList', [...newList])
}
const createFail = (violation: Partial<Violation>) => {
  const violationList: Partial<Violation>[] = getJson('violationList') || []
  const newList = violationList.filter((a) => a.checkCode !== violation.checkCode)
  setJson('violationList', [...newList, violation])
}
//每次同步数据
export const updateCreate = async (t: { [x: string]: any }) => {
  const networkStatus = get('networkStatus')
  const isDeviceError = get('isDeviceError')
  if (networkStatus && !isDeviceError) {
    console.log('违规数据同步')
    message.open({
      key: 'asyncData',
      type: 'loading',
      content: t['asyncData.loading'],
      duration: 0,
    })
    const violationList: Partial<Violation>[] = getJson('violationList') || []
    console.log(violationList)
    const all = violationList.map((a) => {
      return onCreate(a)
        .then(() => {
          return { success: true }
        })
        .catch((error) => {
          if (error?.data?.code == 6003) {
            return { success: true, error }
          }
          return { success: false, error }
        })
    })
    try {
      const results = await Promise.all(all)
      const failedRequests = results.filter((result) => !result.success).length
      if (failedRequests > 0) {
        message.open({
          key: 'asyncData',
          type: 'error',
          content: `${failedRequests} investigation(s) ${t['asyncData.loading.error']}`,
          duration: 3,
        })
        return
      }
      message.open({
        key: 'asyncData',
        type: 'success',
        content: t['asyncData.loading.success'],
        duration: 3,
      })
    } catch (e) {
      message.open({
        key: 'asyncData',
        type: 'error',
        content: t['asyncData.loading.error'],
        duration: 3,
      })
      throw e
    }
  }
}

export const getAllData = async () => {
  try {
    const promises = [getEnums(), getUser(), getViolations()]
    await Promise.all(promises)
  } catch (err) {
    throw err
  }
}
